package com.gregbugaj.nscaffold.transformers;

import java.io.File;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.mapping.Property;
import org.hibernate.mapping.RootClass;
import org.hibernate.type.Type;

import com.gregbugaj.nscaffold.node.PClass;
import com.gregbugaj.nscaffold.node.PropertyInfo;
import com.gregbugaj.nscaffold.type.HibernateTypeResolver;
import com.gregbugaj.nscaffold.type.TypeResolver;
import com.gregbugaj.nscaffold.util.ReflectUtil;

public class HibernateTransformer implements Transformer {
	private List<PClass> classMappings;

	public HibernateTransformer() {
		classMappings=new ArrayList<PClass>();
	}

	@Override
	public List<PClass> getClassMappings() {
		return classMappings;
	}

	@Override
	public void transform() {
		File configFile = new File("hibernate.cfg.xml");
		AnnotationConfiguration cfg = new AnnotationConfiguration();
		cfg.configure(configFile);
		cfg.buildSessionFactory();

		TypeResolver<Type> typeResolver=new HibernateTypeResolver();

		Iterator<RootClass> iter = cfg.getClassMappings();
		while (iter.hasNext()) {
			RootClass rc = iter.next();
			PClass pclass=new PClass();
			pclass.setEntityName(rc.getEntityName());

			try {
				Class<?> entityClass=Class.forName(rc.getEntityName());
				pclass.setEntityClass(entityClass);
			} catch (ClassNotFoundException e) {
				e.printStackTrace();
			}

			System.out.println("-------- "+pclass);
			Iterator<Property> iterProp  = rc.getPropertyClosureIterator();
			while (iterProp.hasNext()) {
				Property rcProp = iterProp.next();


				System.out.println(" =  "+rcProp);
				System.out.println("     "+rcProp.getName());
				System.out.println("     "+rcProp.getType());
				System.out.println("     "+rcProp.getType().getReturnedClass());

				System.out.println("  ");

				PropertyInfo property=new PropertyInfo();
				property.setParent(pclass);
				property.setPropertyName(rcProp.getName());
				property.setType(typeResolver.resolve(rcProp.getType()));	
				property.setCollection(rcProp.getType().isCollectionType());
				property.setPropertyClass(rcProp.getType().getReturnedClass());
				
				//Check entity reference class
				Object of=rcProp.getValue();
				if(rcProp.getType().isCollectionType()){
					try {
						Object val=ReflectUtil.getMethodValue(rcProp.getValue(), of.getClass().getMethod("getElement"));
						String refClassName=(String) ReflectUtil.getMethodValue(val, val.getClass().getMethod("getReferencedEntityName"));
						Class<?> entityRefClass=Class.forName(refClassName);
						property.setPropertyClass(entityRefClass);
					} catch (Exception e) {
						e.printStackTrace();
					} 
				}	
				
				pclass.addProperty(property);
			}
			classMappings.add(pclass);
		}
	}

}
